home *** CD-ROM | disk | FTP | other *** search
Wrap
// VirtualDub - Video processing and capture application // System library component // Copyright (C) 1998-2004 Avery Lee, All Rights Reserved. // // Beginning with 1.6.0, the VirtualDub system library is licensed // differently than the remainder of VirtualDub. This particular file is // thus licensed as follows (the "zlib" license): // // This software is provided 'as-is', without any express or implied // warranty. In no event will the authors be held liable for any // damages arising from the use of this software. // // Permission is granted to anyone to use this software for any purpose, // including commercial applications, and to alter it and redistribute it // freely, subject to the following restrictions: // // 1. The origin of this software must not be misrepresented; you must // not claim that you wrote the original software. If you use this // software in a product, an acknowledgment in the product // documentation would be appreciated but is not required. // 2. Altered source versions must be plainly marked as such, and must // not be misrepresented as being the original software. // 3. This notice may not be removed or altered from any source // distribution. #ifndef f_VD2_SYSTEM_FILE_H #define f_VD2_SYSTEM_FILE_H #ifdef _MSC_VER #pragma once #endif #include <limits.h> #include <stdarg.h> #include <vd2/system/vdtypes.h> #include <vd2/system/vdalloc.h> #include <vd2/system/vdstl.h> #include <vector> #ifdef WIN32 typedef void *VDFileHandle; // this needs to match wtypes.h definition for HANDLE #else #error No operating system target declared?? #endif namespace nsVDFile { enum eSeekMode { kSeekStart=0, kSeekCur, kSeekEnd }; enum eFlags { kRead = 0x00000001, kWrite = 0x00000002, kReadWrite = kRead | kWrite, kDenyNone = 0x00000000, kDenyRead = 0x00000010, kDenyWrite = 0x00000020, kDenyAll = kDenyRead | kDenyWrite, kOpenExisting = 0x00000100, kOpenAlways = 0x00000200, kCreateAlways = 0x00000300, kCreateNew = 0x00000400, kTruncateExisting = 0x00000500, // not particularly useful, really kCreationMask = 0x0000FF00, kSequential = 0x00010000, kRandomAccess = 0x00020000, kUnbuffered = 0x00040000, // much faster on Win32 thanks to the crappy cache, but possibly bad in Unix? kWriteThrough = 0x00080000, kAllFileFlags = 0xFFFFFFFF }; }; class VDFile { protected: VDFileHandle mhFile; vdautoptr2<wchar_t> mpFilename; sint64 mFilePosition; private: VDFile(const VDFile&); const VDFile& operator=(const VDFile& f); public: VDFile() : mhFile(NULL) {} VDFile(const char *pszFileName, uint32 flags = nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting); VDFile(const wchar_t *pwszFileName, uint32 flags = nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting); VDFile(VDFileHandle h); ~VDFile(); // The "NT" functions are non-throwing and return success/failure; the regular functions throw exceptions // when something bad happens. void open(const char *pszFileName, uint32 flags = nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting); // false if failed due to not found or already exists void open(const wchar_t *pwszFileName, uint32 flags = nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting); // false if failed due to not found or already exists bool closeNT(); void close(); bool truncateNT(); void truncate(); // extendValid() pushes the valid threshold of a file out, so that the system allocates // space for a file without ensuring that it is cleared. It is mainly useful for // preallocating a file without waiting for the system to clear all of it. The caveats: // // - only required on NTFS // - requires Windows XP or Windows Server 2003 // - does not work on compressed or sparse files // // As such, it shouldn't normally be relied upon, and extendValidNT() should be the call // of choice. // // enableExtendValid() must be called beforehand, as SeVolumeNamePrivilege must be // enabled on the process before the file is opened! bool extendValidNT(sint64 pos); void extendValid(sint64 pos); static bool enableExtendValid(); sint64 size(); void read(void *buffer, long length); long readData(void *buffer, long length); void write(const void *buffer, long length); long writeData(const void *buffer, long length); bool seekNT(sint64 newPos, nsVDFile::eSeekMode mode = nsVDFile::kSeekStart); void seek(sint64 newPos, nsVDFile::eSeekMode mode = nsVDFile::kSeekStart); bool skipNT(sint64 delta); void skip(sint64 delta); sint64 tell(); bool isOpen(); VDFileHandle getRawHandle(); const wchar_t *getFilenameForError() const { return mpFilename; } // unbuffered I/O requires aligned buffers ("unbuffers") static void *AllocUnbuffer(size_t nBytes); static void FreeUnbuffer(void *p); protected: void open_internal(const char *pszFilename, const wchar_t *pwszFilename, uint32 flags); }; /////////////////////////////////////////////////////////////////////////// template<class T> class VDFileUnbufferAllocator { public: typedef size_t size_type; typedef ptrdiff_t difference_type; typedef T* pointer; typedef const T* const_pointer; typedef T& reference; typedef const T& const_reference; typedef T value_type; template<class U> struct rebind { typedef VDFileUnbufferAllocator<U> other; }; pointer address(reference x) const { return &x; } const_pointer address(const_reference x) const { return &x; } pointer allocate(size_type n, void *p = 0) { return (pointer)VDFile::AllocUnbuffer(n * sizeof(T)); } void deallocate(pointer p, size_type n) { VDFile::FreeUnbuffer(p); } size_type max_size() const throw() { return MAX_INT; } void construct(pointer p, const T& val) { new((void *)p) T(val); } void destroy(pointer p) { ((T*)p)->~T(); } #if defined(_MSC_VER) && _MSC_VER < 1300 char * _Charalloc(size_type n) { return (char *)allocate((n + sizeof(T) - 1) / sizeof(T)); } #endif }; /////////////////////////////////////////////////////////////////////////// class IVDStream { public: virtual const wchar_t *GetNameForError() = 0; virtual sint64 Pos() = 0; virtual void Read(void *buffer, sint32 bytes) = 0; virtual sint32 ReadData(void *buffer, sint32 bytes) = 0; }; class IVDRandomAccessStream : public IVDStream { public: virtual sint64 Length() = 0; virtual void Seek(sint64 offset) = 0; }; class VDFileStream : public VDFile, public IVDRandomAccessStream { private: VDFileStream(const VDFile&); const VDFileStream& operator=(const VDFileStream& f); public: VDFileStream() {} VDFileStream(const char *pszFileName, uint32 flags = nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting) : VDFile(pszFileName, flags) {} VDFileStream(const wchar_t *pwszFileName, uint32 flags = nsVDFile::kRead | nsVDFile::kDenyWrite | nsVDFile::kOpenExisting) : VDFile(pwszFileName, flags) {} VDFileStream(VDFileHandle h) : VDFile(h) {} ~VDFileStream(); const wchar_t *GetNameForError(); sint64 Pos(); void Read(void *buffer, sint32 bytes); sint32 ReadData(void *buffer, sint32 bytes); sint64 Length(); void Seek(sint64 offset); }; class VDMemoryStream : public IVDRandomAccessStream { public: VDMemoryStream(const void *pSrc, uint32 len); const wchar_t *GetNameForError(); sint64 Pos(); void Read(void *buffer, sint32 bytes); sint32 ReadData(void *buffer, sint32 bytes); sint64 Length(); void Seek(sint64 offset); protected: const char *mpSrc; const uint32 mLength; uint32 mPos; }; class VDBufferedStream : public IVDRandomAccessStream { public: VDBufferedStream(IVDRandomAccessStream *pSrc, uint32 bufferSize); ~VDBufferedStream(); const wchar_t *GetNameForError(); sint64 Pos(); void Read(void *buffer, sint32 bytes); sint32 ReadData(void *buffer, sint32 bytes); sint64 Length(); void Seek(sint64 offset); void Skip(sint64 size); protected: IVDRandomAccessStream *mpSrc; vdblock<char> mBuffer; sint64 mBasePosition; uint32 mBufferOffset; uint32 mBufferValidSize; }; class VDTextStream { public: VDTextStream(IVDStream *pSrc); ~VDTextStream(); const char *GetNextLine(); protected: IVDStream *mpSrc; uint32 mBufferPos; uint32 mBufferLimit; enum { kFetchLine, kEatNextIfCR, kEatNextIfLF } mState; enum { kFileBufferSize = 4096 }; vdfastvector<char> mLineBuffer; vdblock<char> mFileBuffer; }; class VDTextInputFile { public: VDTextInputFile(const wchar_t *filename, uint32 flags = nsVDFile::kOpenExisting); ~VDTextInputFile(); inline const char *GetNextLine() { return mTextStream.GetNextLine(); } protected: VDFileStream mFileStream; VDTextStream mTextStream; }; class VDTextOutputFile { public: VDTextOutputFile(const wchar_t *filename, uint32 flags = nsVDFile::kCreateAlways); ~VDTextOutputFile(); void Close(); void PutLine(const char *s); void FormatLine(const char *format, ...); protected: void FormatLine2(const char *format, va_list val); void PutData(const char *s, int len); enum { kBufSize = 4096 }; int mLevel; VDFile mFile; char mBuf[kBufSize]; }; #endif